package org.xxx.epms.models.epms.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.xxx.epms.common.exception.Asserts;
import org.xxx.epms.models.authority.mapper.AdminPermissionMapper;
import org.xxx.epms.models.authority.model.AdminPermission;
import org.xxx.epms.models.epms.cache.AdminCacheService;
import org.xxx.epms.models.epms.dto.AdminParam;
import org.xxx.epms.models.epms.model.Admin;
import org.xxx.epms.models.epms.mapper.AdminMapper;
import org.xxx.epms.models.epms.service.AdminService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.xxx.epms.sequrity.domain.AdminDetails;
import org.xxx.epms.sequrity.util.JwtTokenUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lb
 * @since 2024-06-08
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdminServiceImpl.class);

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private AdminPermissionMapper adminPermissionMapper;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private AdminCacheService adminCacheService;

    @Override
    public Admin register(AdminParam adminParam) {
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminParam, admin);

        //检验参数合法性 -> 管理员编码是否已被注册
        if(adminMapper.selectOne(new QueryWrapper<Admin>().eq("admin_code", admin.getAdminCode()))!= null){
            Asserts.fail("管理员编码已被注册!");
        }else{
            admin.setAdminPassword(passwordEncoder.encode(admin.getAdminPassword()));
            if(adminMapper.insert(admin) > 0) {
                return admin;
            }else {
                Asserts.fail("注册失败!");
            }
        }
        return null;
    }

    @Override
    public String login(AdminParam adminParam) {
        String token = null;
        //密码需要客户端加密后传递
        if(getAdminByAdminCode(adminParam.getAdminCode()) == null){
            Asserts.fail("管理员编码不存在");
        }
        try {
            UserDetails adminDetails = loadUserByUsername(adminParam.getAdminCode());
            if(!passwordEncoder.matches(adminParam.getAdminPassword(), adminDetails.getPassword())){
                Asserts.fail("密码错误");
            }
            if(!adminDetails.isEnabled()){
                Asserts.fail("帐号已被禁用");
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(adminDetails, null, adminDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(adminDetails);
        } catch (AuthenticationException e) {
            LOGGER.warn("登录异常:{}", e.getMessage());
        }
        return token;
    }

    @Override
    public Admin getAdminByAdminCode(String adminCode) {
        //从缓存中获取管理员信息
        Admin admin = adminCacheService.getAdmin(adminCode);
        if(admin != null){
            return admin;
        }
        //从数据库中获取管理员信息并存入缓存
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("admin_code", adminCode);
        admin = adminMapper.selectOne(queryWrapper);
        if(admin != null){
            adminCacheService.setAdmin(admin);
            adminCacheService.setAdminPermissionList(admin.getAdminId(), adminPermissionMapper.selectByAdminId(admin.getAdminId()));
        }
        return admin;
    }

    @Override
    public List<AdminPermission> getAdminPermissionListByAdminId(int adminId) {
        //从缓存中获取管理员权限信息
        List<AdminPermission> adminPermissionList = new ArrayList<>();
        adminPermissionList = adminCacheService.getAdminPermissionList(adminId);
        if(CollUtil.isNotEmpty(adminPermissionList)){
            return adminPermissionList;
        }
        //从数据库中获取管理员权限信息并存入缓存
        adminPermissionList = adminPermissionMapper.selectByAdminId(adminId);
        if(CollUtil.isNotEmpty(adminPermissionList)){
            adminCacheService.setAdminPermissionList(adminId, adminPermissionList);
        }
        return adminPermissionList;
    }

    @Override
    public UserDetails loadUserByUsername(String username){
        //获取管理员信息
        Admin admin = getAdminByAdminCode(username);
        List<AdminPermission> resourceList = getAdminPermissionListByAdminId(admin.getAdminId());
        if (admin != null) {
            return new AdminDetails(admin, resourceList);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }

}
